package smodel;


import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import tcp.HashableTCPServer;
import tcp.NewSessionObserver;
import tcp.SessionHandler;

/**
 * A MultiModel server is useful when you have a list
 * of models that are interchangeable and want to 
 * associate a different model with different clients
 * that are connected.  
 * 
 * To provide a concrete example: 
 * We have 25 chromosomes.  We have an App that displays
 * one chromosome at a time.  Now we want 25 nodes to 
 * connect and use a unique chromosome. 
 * 
 * 
 * @author Kristopher L. Kalish, James Madison University
 * @version 1 - April 15, 2008
 *
 * @param <T> The type of the model data. 
 */
public class MultiModelServer<T> implements NewSessionObserver
{
	private HashableTCPServer<Integer> server; //key model list index to sessions
	private List<T>                    models;
	private int                        currentKey;
	private Properties                 ipToIndex;
	
	public MultiModelServer(int listenPort, InputStream propsStream) throws IOException
	{
		server = new HashableTCPServer<Integer>(listenPort);
		server.addNewSessionObserver(this);
		server.start();
		
		currentKey = 0;
		if(propsStream != null)
		{
			ipToIndex = new Properties();
			ipToIndex.load(propsStream);
		}
	}
	//TODO: handling disconnects could be tricky, but unnecessary for now.
	//it's a good thing to think about though.
	public void handleNewSession(SessionHandler sh)
	{
		System.out.println("Observed new session... will add hash.");
		Object index   = null;
		String address = sh.getRemoteAddress();
		if(ipToIndex != null)
			index = ipToIndex.get(address);
		
		if(index != null)
		{
			System.out.println("Hashing " + address + " to key " + index);
			server.addHash(Integer.parseInt((String)index), sh);
		}
		else
		{
			System.out.println("Warning: " + address + " not found in " +
					"configuration file, using an arbitrary index.\n" +
					"This will most likely result in unpredictable " +
					"behavior.\nUsing index " + currentKey + ".");
			server.addHash(currentKey++, sh);
		}
	}
	
	public void setModels(List<T> models)
	{
		this.models = models;
		
		for(int i = 0; i < models.size(); i++)
		{
			//System.out.println("Attempting to send to " + i + ": " + models.get(i)); //debug
			if(server.sessionKeyExists(i))
			{
				System.out.println(i + " exists!!"); //debug
				server.sendTo(i, models.get(i));
			}
		}
	}
	
	/**
	 * TODO: Implement this.  
	 * This will let you change the state of a single model in the list.
	 * @param index
	 * @param data
	 */
	public void setState(int index, T data)
	{
	}
}
